package vooga.core;

import java.io.File;
import vooga.core.Player;
import vooga.core.VoogaView;
import vooga.entities.Entity;
import vooga.xml.XMLException;
import vooga.xml.handlers.EntityHandler;
import vooga.xml.handlers.LayerHandler;

/**
 * Create levels for game.
 * 
 * @author Congyi Wu
 * 
 * adapted from gap.world
 */
public class XMLLevelFactory implements vooga.core.LevelFactoryInterface {
	public static final String LEVEL_FILE_PREFIX = "level";
	public static final String GAMES_FOLDER = "games";
	public static final String LEVEL_FOLDER = "data";
	
	public static final Class LEVEL_CONSTRUCTOR_ARGS[] = {VoogaView.class, Player.class};
	
	protected String myGame;
	
	/**
	 * 
	 * @param gamePackage game sub package name (i.e. "breakout")
	 */
	public XMLLevelFactory(String gamePackage)
	{
		myGame = gamePackage;
	}
	
	public AbstractLevel getLevel(VoogaView view, Player player)
	{
        AbstractLevel level;
        player.getStatus().setGameName(myGame);
        java.util.HashSet<Entity> entities = new java.util.HashSet<Entity>();
                
        // instantiate the level
        Object args[] = {view, player};
        try
        {
        	level = (AbstractLevel) Class.forName(GAMES_FOLDER + "." + myGame + "." + "Level").
        		getConstructor(LEVEL_CONSTRUCTOR_ARGS).newInstance(args);
		}
        catch (Exception e)
        {
			view.showError(Game.BROKEN_GAME_ERROR);
			e.printStackTrace();
			return null;
		}

        // register World specific handlers
        vooga.xml.XMLDocument doc = new vooga.xml.XMLDocument();
        doc.registerHandler(EntityHandler.ENTITY_ENTITY, new vooga.xml.handlers.EntityHandler());
        doc.registerHandler(LayerHandler.LAYER_ENTITY, new vooga.xml.handlers.LayerHandler());
        doc.registerHandler("", new vooga.xml.handlers.FactoryHandler());

        int levelNum = player.getStatus().getLevelNumber();
        File levelFile = new File(GAMES_FOLDER + "/" + myGame + "/" + LEVEL_FOLDER, LEVEL_FILE_PREFIX + levelNum + ".xml");
        
        //no more levels
        if(!levelFile.exists())
        	return null;
       
       
        // create entities and layers from XML specification
    	try
		{
    	    org.w3c.dom.Node root = doc.loadFromFile(levelFile);
			for (org.w3c.dom.Node current : vooga.xml.XMLHandler.getSubNodes(root, EntityHandler.ENTITY_ENTITY))
				entities.add((Entity)doc.getHandler(current.getNodeName()).handleNode(current, null));        

			for (org.w3c.dom.Node current : vooga.xml.XMLHandler.getSubNodes(root, LayerHandler.LAYER_ENTITY))
				level.addLayer((Layer)doc.getHandler(current.getNodeName()).handleNode(current, null));        
		}
		catch (XMLException e) {
			view.showError(Game.BROKEN_GAME_ERROR);
			e.printStackTrace();
		}
        
        //add entities
	    level.addEntities(entities);
	    
	    return level;
	}
}
